          PH.ARGS DRPT,BRCHS,BR,SD,ED,SLCT,SLIST,PG.BREAK,LEVEL,CUSLIST,SOURCE,FITEM
** Version# 3.0002[74] - 06/10/2014 - 09:21am - TSMITH - eclipse
*** V3.0002 Change - Custom Coding . - 06/10/2014 - TSMITH - eclipse
** Copied from BP SOE.PHR.CREDIT.REASON Version# 3 - 06/09/2003 - 10:50am - MHOOTEN - develop

*** Subroutine: SOE.PHR.CREDIT.REASON
*-------------------------------------------------------------------------*
*** This is the Phantom routine for the Credit Reason Report, which
*** summarizes the credits that have been entered into the system along
*** with the reason for their return.
***
*** The Customer and Salesperson/Writer Select options are used to filter
*** the original Sales Order that an item is returned from.
***
*** When the User has specified that they want to see returns where the
*** original Sales Order was from the warehouse AND where the orinal order
*** was a Direct, the data will be broken out separately for both.
*** Anotherwords, if Customer X returned items from two separate orders,
*** where one was a Direct and the other was sold from the warehouse,
*** there would be one line on the report for the Direct order and one for
*** the warehouse sale. There will also two subtotal lines, one for the
*** Direct and one for the warehouse sale.
***
*** Since the User has the option of 'Page Breaking' on Sort by, 'Grand
*** Totals' for the report are not printed. Instead the report prints a
*** Sales Source Summary for the whole report, which is essentially the
*** same thing, just displayed in a different manner.
*-------------------------------------------------------------------------*
*** DRPT     - REPORTS File record for this report.                   [IN]
*** BRCHS    - Branches to report date for. Only Credits made at      [IN]
***            this/these Branches will be included on the report.
*** BR       - Literal string of Branches entered by the User, used   [IN]
***            for the report heading.
*** SD       - Start Date. Only Credits (Invoiced) on or after this   [IN]
***            date will be included on the report.
*** ED       - End Date. Only Credits (Invoiced on or before this     [IN]
***            date will be included on the report.
*** SLCT     - Select and Sort by. Options include:                   [IN]
***             > Writer
***             > Inside Salesperson
***             > Outside Salesperon
*** SLIST    - Select and Sort by entities to report data for.        (IN)
*** PG.BREAK - Page Break on Sorb by option.
*** LEVEL    - Customer Level, Bill-To or Ship-To.                    [IN]
*** CUSLIST  - Customers to report data for.                          (IN)
*** SOURCE   - Sales Source to report Credit data for. If the return  [IN]
***            was for something sold directly from the warehouse, or
***            it was Direct from a Vendor, this option will allow
***            the User to specify which of the two types they want
***            to see. Options include:
***             > Warehouse
***             > Direct
***             > Both
*-------------------------------------------------------------------------*
*** COMMON Variables Used: DRPT$, LED, LD
*-------------------------------------------------------------------------*

          *** Go initialize some data to use for building our report...
          GOSUB INIT

*-------------------------------------------------------------------------*
          *** Update the phantom status...
          WRITE 'Selecting...' ON PHSTFILE,PID$

          *** Go try and select data for the report...
          GOSUB SEL.IDS

          *** Update the phantom status...
          WRITE 'Spooling...' ON PHSTFILE,PID$
*-------------------------------------------------------------------------*

          *** Go build our Report's Heading and Title...
          GOSUB SET.HEADING

*** Turn our printer on and print the report...
          PRINTER.ON 1400,TITLE,DOC.ID,HDG,RPT.DFLT=DRPT

          *** Print any Additional Select criteria...
          FILTER.PRINT "S",FITEM

          *** Activate a sorted list of our Tempfile records...
          SSELECT TEMPFILE

          LOOP
             READNEXT TID ELSE EXIT

             READ TMP FROM TEMPFILE,TID ELSE TMP = ''

             *** Go print this record for the report...
             GOSUB PRINT.REC
          REPEAT

          *** If we printed any data on the report, go print the last
          *** set of Totals...
          IF ITEM.CT # 0 THEN
             *** Go print the Original Sales Source Totals...
             GOSUB PRINT.SOURCE.TOTALS
             *** Go print the Customer Totals...
             GOSUB PRINT.CUSTOMER.TOTALS
             *** Go print the Salesperson/Writer Totals...
             GOSUB PRINT.SPERSON.TOTALS

             *** Go print the Sales Source, Customer and Salesperon
             *** Summaries...
             GOSUB PRINT.SUMMARIES
          END

*** Turn our printer off and clean up after ourselves...
          PRINTER.OFF DOC.ID

          UT.TEMPFILE.DELETE FLNM.ID
          UT.PH.CLEANUP

          IF ITEM.CT = 0 THEN
             COUNT.MSG = ' - No Items Found'
          END ELSE
             COUNT.MSG = ' - is Complete'
          END

          SEND.MESSAGE 'Phantom',USER.ID,TITLE:COUNT.MSG

          STOP
*-------------------------------------------------------------------------*
INIT:     * Initialize data we'll be using to build our report...

          BRS = BR
          BR  = ''

          SDT = OCONV(SD,'D4/')
          EDT = OCONV(ED,'D4/')

          IF FITEM = '' THEN FILTER.FLAG = NO ELSE FILTER.FLAG = YES

          *** We'll count the number of items we print on the report, so
          *** we know what kind of message to send the User when the
          *** report has finished using...
          ITEM.CT  = 0

          *** We'll use these counters to know when to print a sub-heading
          *** for the Customer and the Sales Source...
          CUS.ITEM.CT    = 0
          SLSP.ITEM.CT   = 0
          SOURCE.ITEM.CT = 0

          LAST.SOURCE    = '@@@'
          LAST.SLSPERSON = '@@@'
          LAST.CUSTOMER  = '@@@'

          SOURCE.TOTALS  = ''
          CUS.TOTALS     = ''
          SLSP.TOTALS    = ''

          *** We'll use these arrays for the Summaries we print at the
          *** end of the report...
          SOURCE.SUMMARY = ''
          REASON.SUMMARY = ''
          SLSP.SUMMARY   = ''
          CUS.SUMMARY    = ''

          *** We'll use these arrays for the Summaries for each
          *** Salesperson/Writer if we are Page Breaking on them...
          SLSP.RSUMRY    = ''
          SLSP.CSUMRY    = ''

          *** Set up some dashed lines to use for printing totals...
          DASHED.LINES   = STR('-',10):'  ':STR('-',10)

          *** Create a Tempfile to store our report data in...
          UT.TEMPFILE.CREATE FLNM.ID,TEMPFILE

          RETURN
*-------------------------------------------------------------------------*
SEL.IDS: * Try and select data for the report...

          *** Get Sales Records from the AR File, for the Start and End
          *** Date the User selected...
          JLI.SELECT MESS,SD,ED,,1

          LOOP
             READNEXT ID ELSE EXIT

             OID  = FIELD(ID,'.',1)
             *** Need to add a 0 onto our value so that our LOCATE will
             *** work properly. (Convert our '00#' to '#')...
             INVN = FIELD(ID,'.',2) + 0

             *** Make sure this is a valid order...
             MATREAD LED FROM LEDFILE,OID                  ELSE CONTINUE
             LOCATE INVN IN LED(8)<1> SETTING GEN          ELSE CONTINUE

             *** Pull all the Line items (Ledger Detail Ids) from the
             *** order...
             LDIDS = LED(48)<1,GEN>

             *** Go check whether any of them were 'returned'...
             GOSUB CHECK.LINE.ITEMS
          REPEAT

          RETURN
*-------------------------------------------------------------------------*
CHECK.LINE.ITEMS: * Check whether any of the Line Items we came in here
                  * with were returned...

          LD.CT = DCOUNT(LDIDS,SVM)

          FOR LDN = 1 TO LD.CT
             LDID = LDIDS<1,1,LDN>
             *** Load our LD array...
             LD.GET LDID
             PN   = LD(1)

             IF NOT(NUM(PN)) OR PN = '' THEN CONTINUE

             *** Since Sales Order Quantities are STORED as a negative
             *** value, then we know that an Item Qty with a positive
             *** value is a Return...
             QTY = SUM(LD(5)<1,GEN>) + SUM(LD(6)<1,GEN>)

             *** If this isn't a return then skip it...
             IF QTY <= 0                THEN CONTINUE

             *** Go run the Origianl Order through our filters...
             GOSUB CHECK.ORIGINAL.ORDER
          NEXT LDN

          RETURN
*-------------------------------------------------------------------------*
CHECK.ORIGINAL.ORDER: *** Make sure that the original order (the order the
                      *** item is being returned from) meets all the
                      *** Select criteria...

          *** Get the Original Order this item is being returned
          *** from...
          ORIGINAL.OID  = FIELD(LD(44),'.',1)
          *** Need to add a 0 onto our value so that our LOCATE will
          *** work properly. (Convert our '00#' to '#')...
          OINVN         = FIELD(LD(44),'.',2) + 0

          *** If the Original Order doesn't have an active Ledger
          *** record then skip this line item. (We'll read the record
          *** into 'OLED' so that we don't overwrite our LED array).
          MATREAD OLED FROM LEDFILE,ORIGINAL.OID ELSE RETURN

          *** Set the Gen of our Original Order...
          LOCATE OINVN IN OLED(8)<1> SETTING OGEN ELSE RETURN

          *** Make sure the Shipping Branch is one that was selected
          *** by the User...
          SHIP.BR = OLED(2)<1,OGEN,2>
          LOCATE SHIP.BR IN BRCHS<1> SETTING XX ELSE RETURN

          *** Check to see if the original order was a direct...
          IF OLED(33)<1,OGEN> THEN IS.DIRECT = YES ELSE IS.DIRECT = NO

          *** If they only want to see Returns where the original
          *** sale was made from a warehouse, but this one was
          *** Direct from a Vendor, then skip it...
          IF SOURCE = 'Warehouse' AND IS.DIRECT THEN RETURN

          *** If they only want to see Returns where the original
          *** sale was made from a Vendor, but this one was from
          *** a warehouse then skip it...
          IF SOURCE = 'Direct' AND NOT(IS.DIRECT) THEN RETURN

          *** Check the Salesperson or Writer...
          BEGIN CASE
          CASE SLCT = 'Writer'
             SALESP = OLED(73)<1,GEN>
          CASE SLCT = 'Inside Salesperson'
             SALESP = OLED(34)<1,GEN>
          CASE SLCT = 'Outside Salesperson'
             SALESP = OLED(72)<1,GEN>
          END CASE

          IF SLIST THEN
             *** If they have specified certain Salespeople or
             *** Writers, but the Oringial Order doesn't meet that
             *** criteria then skip it...
             LOCATE SALESP IN SLIST<1> SETTING NADA ELSE RETURN
          END

          *** Check the Customer...
          IF LEVEL = 'Bill-To' THEN
             CNUM  = OLED(1)<1,GEN>
          END ELSE
             CNUM  = OLED(5)<1,GEN>
          END

          IF CUSLIST THEN
             *** If they have specified certain Customers, but the
             *** Oringial Order doesn't meet that criteria, then
             *** skip it...
             LOCATE CNUM IN CUSLIST<1> SETTING NADA ELSE RETURN
          END

          *** Filter against any 'Additional Select' criteria...
          IF FILTER.FLAG THEN
             FILTER.SELECT SKIP.FLAG,ORIGINAL.OID,OGEN,FITEM
             IF SKIP.FLAG THEN RETURN
          END

          *** We passed all the filters so we can go add a record in our
          *** Tempfile...
          GOSUB ADD.REC

          RETURN
*-------------------------------------------------------------------------*
ADD.REC:  *** Add a record in our Tempfile for the Returned item we got
          *** to here with...

          *** Get the Customer Sort by...
          READV CSORT FROM CUSFILE,CNUM,8 ELSE CSORT = CNUM

          *** Our Reason for Return code is stored on the Return Order...
          REASONCODE    = LD(46)
          *** We'll stick a space in from of our Null string so that
          *** this record will get sorted at the beginning...
          IF REASONCODE = '' THEN REASONCODE = ' >NULL<'

          *** We'll stick a space in from of our Null string so that
          *** this record will get sorted at the beginning...
          IF SALESP = '' THEN SALESP = LED(72)<1,GEN>

          SHIP.VIA      = LED(70)<1,GEN>
          ORDER.ID      = ID
          CNUM          = LED(1)<1,GEN>
          DESC          = TRANS('PRODUCT',LD(1),1,'X')<1,1,1>
          WRITER        = LED(73)<1,GEN>
          *** We'll build our Tempfile Id based on the Sort order we want.
          *** We want our Warehouse info to get listed before the Direct
          *** info, so we can just use our Direct flag, which will be
          *** a 1 or a 0, in the Id...
          TEMP.ID = SALESP:'~':CSORT:'~':IS.DIRECT:'~':REASONCODE:'~':CNUM:'~':ORDER.ID:'~':SHIP.VIA:'~':DESC:'~':WRITER

          READ TEMPREC FROM TEMPFILE,TEMP.ID ELSE TEMPREC = ''

          AMOUNT = QTY * LD(8)<1,GEN>


          *** Increment the number of line items...
          TEMPREC<1> += 1
          *** Add to the quantities...
          TEMPREC<2> += QTY
          *** Add to the quantities...
          TEMPREC<3> += AMOUNT


          WRITE TEMPREC ON TEMPFILE,TEMP.ID

          RETURN
*-------------------------------------------------------------------------*
SET.HEADING:* Set the Heading and Title for our Report...

          TITLE = 'Credit Reason Report for ':SDT:' - ':EDT

          HDG   = TITLE

*** Add the Select and Sort by to the second line of our heading...
          IF SLIST THEN
             HDG<1,2> = SLCT:': '
             IF DCOUNT(SLIST,VM) > 1 THEN
                HDG<1,2> := '*Multi* - '
             END ELSE
                ONE.ITEM.SLIST    = OCONV(SLIST,'TINITIALS;X;3;3')
                *** In case the User Id Record has been deleted from the
                *** Initials File, we'll just use the Id...
                IF ONE.ITEM.SLIST = '' THEN ONE.ITEM.SLIST = SLIST

                HDG<1,2> := ONE.ITEM.SLIST:' - '
             END
          END

*** Add the Customer to the second line of our heading...
          IF CUSLIST THEN
             HDG<1,2> := LEVEL:' Customer: '

             IF DCOUNT(SLIST,VM) > 1 THEN
                HDG<1,2> := '*Multi* - '
             END ELSE
                HDG<1,2> := OCONV(CUSLIST,'TENTITY;X;9;9'):' - '
             END
          END

*** Add the Sales Source we'll be showing credits for, to the second
*** line of our heading...
          IF SOURCE  = 'Both' THEN
             HSOURCE = 'Warehouse and Direct'
          END ELSE
             HSOURCE = SOURCE
          END

          HDG<1,2> := 'Sales Source: ':HSOURCE

*** Build the data columns...
          *** Salesperson/Writer...
          HDG<1,4>  = SLCT:STR('.',25 - LEN(SLCT)):'  '

          HDG<1,4> := 'ID       ':LEVEL:' Customer':STR('.',19):'  '
          HDG<1,4> := 'Ship Via':STR('.',8):'  Sales Source  '
          HDG<1,4> := 'Return Code':STR('.',19):'  Line Items  '
          HDG<1,4> := 'Quantity..  Dollar Amount..'
          HDG<1,4> := 'Order.......  Description........................  '
          HDG<1,4> := 'Writer..'


*** We'll use the length of our data columns for the report width...
          WDTH     = LEN(HDG<1,4>)

*** Tack the page number onto the first line of our heading...
          H1LENGTH = LEN(HDG<1,1>)
          *** We'll have it line up directly with the edge of our report...
          HDG<1,1> := SPACE(WDTH - H1LENGTH - 11):'Page: ^####'

*** Display the Territories/Branches in the 3rd line of our heading...
          *** If there are too many branches to fit on the report, we'll
          *** only display those that will...
          IF LEN(BRS) > (WDTH - 15) THEN
             BRS = BRS[1,WDTH - 15]:'...'
          END

          HDG<1,3> = 'Branch(es): ':BRS

          RETURN
*-------------------------------------------------------------------------*
PRINT.REC: *** Print one record from our Tempfile...

          *** Parse out the data from our Tempfile Id.
          SLS.PERSON   = FIELD(TID,'~',1)
          DIRECT.ORDER = FIELD(TID,'~',3)
          REASON.CODE  = FIELD(TID,'~',4)
          CNUMBER      = FIELD(TID,'~',5)
          ORDER        = FIELD(TID,'~',6)
          SHIP.VIA     = FIELD(TID,'~',7)
          DESC         = FIELD(TID,'~',8)
          WRITER       = FIELD(TID,'~',9)


          *** Save these values as we used them for our Temfile Id...
          SAVE.SPERSON = SLS.PERSON
          SAVE.REASON  = REASON.CODE

          *** If the SLS.PERSON or REASON.CODE values were null, we
          *** we set them to " >NULL<" so that they'd get sorted first.
          *** We'll need to trim off any spaces that we may have added to
          *** get the record sorted at the beginning...
          SLS.PERSON   = TRIM(SLS.PERSON)
          REASON.CODE  = TRIM(REASON.CODE)

          *** Parse out the data from our Tempfile record...
          LITEMS = TMP<1> ; *Line Items
          QTYS   = TMP<2> ; *Item Qtys
          AMT$   = TMP<3> ; *Item Dollar Amounts

*** Check whether we need to print Subtotals first...
          *** We don't want to print more than one blank line (in case
          *** we don't print totals since there was only one line of data
          *** printed) so we'll use a flag to determine when a blank line
          *** should print instead of a total...
          BLANK.LINE.PRINTED = NO

          BEGIN CASE
          *** If we're on a new Salesperson...
          CASE LAST.SLSPERSON # '@@@' AND LAST.SLSPERSON # SAVE.SPERSON
             *** Go print the Original Sales Source Totals...
             GOSUB PRINT.SOURCE.TOTALS
             *** Go print the Customer Totals...
             GOSUB PRINT.CUSTOMER.TOTALS
             *** Go print the Salesperson/Writer Totals...
             GOSUB PRINT.SPERSON.TOTALS
          *** If we're on a new Customer...
          CASE LAST.CUSTOMER # '@@@' AND LAST.CUSTOMER # CNUMBER
             *** Go print the Original Sales Source Totals...
             GOSUB PRINT.SOURCE.TOTALS
             *** Go print the Customer Totals...
             GOSUB PRINT.CUSTOMER.TOTALS
          *** If we're on a new Sales Source...
          CASE LAST.SOURCE # '@@@' AND LAST.SOURCE # DIRECT.ORDER
             *** Go print the Original Sales Source Totals...
             GOSUB PRINT.SOURCE.TOTALS
          END CASE

*** Print the Detail...
          *** We only want to print the Salesperson once...
          IF SLSP.ITEM.CT  = 0 THEN
             IF SLS.PERSON # '>NULL<' THEN
                SPERSON    = OCONV(SLS.PERSON,'TINITIALS;X;3;3')
                *** In case the User Id Record has been deleted from the
                *** Initials File, we'll just use the Id...
                IF SPERSON = '' THEN SPERSON = SLS.PERSON

                PRINT SLS.PERSON                             "L#25":'  ':
             END ELSE
                PRINT SLS.PERSON                          "L#25":'  ':
             END
          END ELSE
             PRINT SLS.PERSON                             "L#25":'  ':

          END

          *** If this is the first item we're printing for this Customer,
          *** print their Name and default Ship Via...
          IF CUS.ITEM.CT = 0 THEN
             READV CNAME FROM CUSFILE,CNUMBER,1 ELSE CNAME = CNUMBER
             PRINT '&':CNUMBER                          "L#6":'  ':
             PRINT CNAME                                "L#35":'  ':



             PRINT SHIP.VIA                            "L#16":'  ':
          END ELSE
             READV CNAME FROM CUSFILE,CNUMBER,1 ELSE CNAME = CNUMBER

             PRINT '&':CNUMBER                          "L#6":'  ':
             PRINT CNAME                                "L#35":'  ':


             PRINT SHIP.VIA                            "L#16":'  ':

*             PRINT SPACE(62):
          END

          *** If this is the first item we're printing for this Sales
          *** Source, print it...
          *IF SOURCE.ITEM.CT = 0 THEN
             IF DIRECT.ORDER THEN
                PRINT 'Direct'                         "L#12":'  ':
             END ELSE
                PRINT 'Warehouse'                      "L#12":'  ':
             END
          *END ELSE
          *      PRINT SPACE(14):
          *END

          PRINT REASON.CODE                            "L#30":'  ':
          PRINT LITEMS                                 "R#10":'  ':
          PRINT QTYS                                   "R#10":'  ':
          PRINT OCONV(AMT$,"MR9")                      "R2#13":'  ':
          PRINT ORDER                                  "L#12":'  ':
          PRINT DESC                                   "L#35":'  ':
          PRINT WRITER                                 "L#8":'  ':
          PRINT TEMP.ID                                "L#200"




*** Add to the Credit Reason Summary Totals...
          *** 'DIRECT.ORDER' will be zero if we're dealing with a
          *** warehouse sale...
          ATTB = DIRECT.ORDER + 2

          *** If we're page breaking on Salesperson/Writer then we'll
          *** also be printing Summaries for them...
          IF PG.BREAK THEN
             *** We're storing the Reason Code in attribute 1, the
             *** correlating warehouse sales in attribute 2 and the Directs
             *** in attribute 3...
             LOCATE SAVE.REASON IN SLSP.RSUMRY<1> BY "AL" SETTING SPOS ELSE
                SLSP.RSUMRY = INSERT(SLSP.RSUMRY,1,SPOS;SAVE.REASON)

                *** We want 'nothing' to get stored for the Sales Source
                *** that we are NOT currently on...
                IF DIRECT.ORDER THEN
                   DVAL = 0 ; WVAL = ''
                END ELSE
                   DVAL = ''; WVAL = 0
                END

                SLSP.RSUMRY = INSERT(SLSP.RSUMRY,2,SPOS;WVAL)
                SLSP.RSUMRY = INSERT(SLSP.RSUMRY,3,SPOS;DVAL)
             END

             SLSP.RSUMRY<ATTB,SPOS,1> += LITEMS
             SLSP.RSUMRY<ATTB,SPOS,2> += QTYS
             SLSP.RSUMRY<ATTB,SPOS,3> += AMT$
          END

          *** Add to the Credit Reason Summary Totals that we'll print
          *** at the end of the report...

          *** We're storing the Reason Code in attribute 1, the
          *** correlating warehouse sales in attribute 2 and the Directs
          *** in attribute 3...
          LOCATE SAVE.REASON IN REASON.SUMMARY<1> BY "AL" SETTING RPOS ELSE
             REASON.SUMMARY = INSERT(REASON.SUMMARY,1,RPOS;SAVE.REASON)

             *** We want 'nothing' to get stored for the Sales Source
             *** that we are NOT currently on...
             IF DIRECT.ORDER THEN
                DVAL = 0 ; WVAL = ''
             END ELSE
                DVAL = ''; WVAL = 0
             END

             REASON.SUMMARY = INSERT(REASON.SUMMARY,2,RPOS;WVAL)
             REASON.SUMMARY = INSERT(REASON.SUMMARY,3,RPOS;DVAL)
          END

          REASON.SUMMARY<ATTB,RPOS,1> += LITEMS
          REASON.SUMMARY<ATTB,RPOS,2> += QTYS
          REASON.SUMMARY<ATTB,RPOS,3> += AMT$

*** Add to our Totals...
          *** 'DIRECT.ORDER' will be zero if we're dealing with a
          *** warehosue sale...
          ATTRIBUTE = DIRECT.ORDER + 1

          *** Sales Source Totals...
          SOURCE.TOTALS<1> += LITEMS
          SOURCE.TOTALS<2> += QTYS
          SOURCE.TOTALS<3> += AMT$

          *** Customer Totals...
          CUS.TOTALS<ATTRIBUTE,1>  += LITEMS
          CUS.TOTALS<ATTRIBUTE,2>  += QTYS
          CUS.TOTALS<ATTRIBUTE,3>  += AMT$

          *** Salesperson/Writer Totals...
          SLSP.TOTALS<ATTRIBUTE,1> += LITEMS
          SLSP.TOTALS<ATTRIBUTE,2> += QTYS
          SLSP.TOTALS<ATTRIBUTE,3> += AMT$

          ITEM.CT        += 1
          SOURCE.ITEM.CT += 1
          CUS.ITEM.CT    += 1
          SLSP.ITEM.CT   += 1

          *** Save these values so we know whether to print subtotals
          *** before printing the next record...
          LAST.SOURCE     = DIRECT.ORDER
          LAST.CUSTOMER   = CNUMBER
          LAST.SLSPERSON  = SAVE.SPERSON

          RETURN
*-------------------------------------------------------------------------*
PRINT.SOURCE.TOTALS: *** Print the Sales Source Totals...

          *** If we printed more than one line of data on the report
          *** for this Sales Source...
          IF SOURCE.ITEM.CT > 1 THEN
             IF LAST.SOURCE = 1 THEN
                LSOURCE = 'Direct'
             END ELSE
                LSOURCE = 'Warehouse'
             END

             TOTAL.STRING = LSOURCE:' Totals: '

             TOTALS       = LOWER(SOURCE.TOTALS)

             *** Go use our generic code for printing all Totals...
             GOSUB PRINT.TOTALS
          END

          SOURCE.TOTALS   = ''
          SOURCE.ITEM.CT  = 0

          RETURN
*-------------------------------------------------------------------------*
PRINT.CUSTOMER.TOTALS: *** Here's where we'll print the Customer Totals.
                       *** We will have 2 lines of Totals, one for returns
                       *** where the Warehouse was the original Sales
                       *** Source and the other for returns where the
                       *** original Sale was a Direct Order...

          READV LAST.CNAME FROM CUSFILE,LAST.CUSTOMER,1 ELSE
             LAST.CNAME = LAST.CUSTOMER
          END

          *** If we've printed more than one line of data on the report
          *** for this customer...
          IF CUS.ITEM.CT > 1 THEN
             TOT.STRING  = 'Totals for Customer: ':LAST.CNAME

             *** Set up the label for the Customer's Warehouse Totals...
             IF CUS.TOTALS<1> THEN
                TOTALS        = CUS.TOTALS<1>
                TOTAL.STRING  = 'Warehouse ':TOT.STRING

                *** Go use our generic code for printing all Totals...
                GOSUB PRINT.TOTALS
             END

             *** Set up the label for the Customer's Direct Totals...
             IF CUS.TOTALS<2> THEN
                TOTALS        = CUS.TOTALS<2>
                TOTAL.STRING  = 'Direct ':TOT.STRING

                *** Go use our generic code for printing all Totals...
                GOSUB PRINT.TOTALS
             END
          END ELSE
             *** Otherwise, print a blank line, if we haven't done
             *** so already...
     *        IF NOT(BLANK.LINE.PRINTED) THEN PRINT
     *        BLANK.LINE.PRINTED = YES
          END

*** If we're Page Breaking on Salesperson/Writer add to a Summary for
*** them...
          IF PG.BREAK THEN
             LOCATE LAST.CNAME IN SLSP.CSUMRY<1> BY "AL" SETTING SCPOS ELSE
                *** If we found a new one, we'll need to move everything
                *** over accordingly...
                SLSP.CSUMRY = INSERT(SLSP.CSUMRY,1,SCPOS;LAST.CNAME)

                *** Warehouse Sales...
                IF CUS.TOTALS<1> THEN INIT.VALUE = 0 ELSE INIT.VALUE = ''
                SLSP.CSUMRY = INSERT(SLSP.CSUMRY,2,SCPOS;INIT.VALUE)

                *** Directs...
                IF CUS.TOTALS<2> THEN INIT.VALUE = 0 ELSE INIT.VALUE = ''
                SLSP.CSUMRY = INSERT(SLSP.CSUMRY,3,SCPOS;INIT.VALUE)
             END

             *** Warehouse Sales...
             IF CUS.TOTALS<1> THEN
                SLSP.CSUMRY<2,SCPOS,1> += CUS.TOTALS<1,1> ; *Line Items
                SLSP.CSUMRY<2,SCPOS,2> += CUS.TOTALS<1,2> ; *Qtys
                SLSP.CSUMRY<2,SCPOS,3> += CUS.TOTALS<1,3> ; *$ Amount
             END

             *** Directs...
             IF CUS.TOTALS<2> THEN
                SLSP.CSUMRY<3,SCPOS,1> += CUS.TOTALS<2,1> ; *Line Items
                SLSP.CSUMRY<3,SCPOS,2> += CUS.TOTALS<2,2> ; *Qtys
                SLSP.CSUMRY<3,SCPOS,3> += CUS.TOTALS<2,3> ; *$ Amount
             END
          END

*** Add to our Overall Summary Totals, which we'll print at the end of the
*** report...

          LOCATE LAST.CNAME IN CUS.SUMMARY<1> BY "AL" SETTING CPOS ELSE
             *** If we found a new one, we'll need to move everything
             *** over accordingly...
             CUS.SUMMARY = INSERT(CUS.SUMMARY,1,CPOS;LAST.CNAME)

             *** Warehouse Sales...
             IF CUS.TOTALS<1> THEN INIT.VALUE = 0 ELSE INIT.VALUE = ''
             CUS.SUMMARY = INSERT(CUS.SUMMARY,2,CPOS;INIT.VALUE)

             *** Directs...
             IF CUS.TOTALS<2> THEN INIT.VALUE = 0 ELSE INIT.VALUE = ''
             CUS.SUMMARY = INSERT(CUS.SUMMARY,3,CPOS;INIT.VALUE)
          END

          *** Warehouse Sales...
          IF CUS.TOTALS<1> THEN
             CUS.SUMMARY<2,CPOS,1> += CUS.TOTALS<1,1> ; *Line Items
             CUS.SUMMARY<2,CPOS,2> += CUS.TOTALS<1,2> ; *Qtys
             CUS.SUMMARY<2,CPOS,3> += CUS.TOTALS<1,3> ; *$ Amount
          END

          *** Directs...
          IF CUS.TOTALS<2> THEN
             CUS.SUMMARY<3,CPOS,1> += CUS.TOTALS<2,1> ; *Line Items
             CUS.SUMMARY<3,CPOS,2> += CUS.TOTALS<2,2> ; *Qtys
             CUS.SUMMARY<3,CPOS,3> += CUS.TOTALS<2,3> ; *$ Amount
          END

*** Clear out our totals...
          CUS.TOTALS  = ''
          CUS.ITEM.CT = 0

          RETURN
*-------------------------------------------------------------------------*
PRINT.SPERSON.TOTALS: * Here is where w'll print the Salesperon/Writer
                      * Totals. We will have 2 lines of Totals, one for
                      * returns where the Warehouse was the original sales
                      * source and the other for returns where the
                      * original sale was a Direct Order...

          IF LAST.SLSPERSON # ' >NULL<' THEN
             LAST.SPERSON    = OCONV(LAST.SLSPERSON,'TINITIALS;X;3;3')
             *** In case the User Id Record has been deleted from the
             *** Initials File, we'll just use the Id...
             IF LAST.SPERSON = '' THEN LAST.SPERSON = LAST.SLSPERSON
          END ELSE
             LAST.SPERSON    = TRIM(LAST.SLSPERSON)
          END

          *** If we've printed more than one line of data on the report
          *** for this Salesperson/Writer...
          IF SLSP.ITEM.CT > 1 THEN
             TOT.STRING  = 'Totals for ':SLCT:': ':LAST.SPERSON

             *** Set up the label for the Salesperson's Warehouse Totals...
             IF SLSP.TOTALS<1> THEN
                TOTALS        = SLSP.TOTALS<1>
                TOTAL.STRING  = 'Warehouse ':TOT.STRING

                *** Go use our generic code for printing Totals...
                GOSUB PRINT.TOTALS
             END

             *** Set up the label for the Salesperson's Direct Totals...
             IF SLSP.TOTALS<2> THEN
                TOTALS        = SLSP.TOTALS<2>
                TOTAL.STRING  = 'Direct ':TOT.STRING

                *** Go use our generic code for printing Totals...
                GOSUB PRINT.TOTALS
             END
          END ELSE
             *** Otherwise, as long as we're not Page Breaking on
             *** Salespeople/Writers...
             IF NOT(PG.BREAK) THEN
                *** Print a blank line, if we haven't done so already...
                IF NOT(BLANK.LINE.PRINTED) THEN
                BLANK.LINE.PRINTED = YES
             END
          END
          END

*** Add to our Source and Salesperson/Writer Summary Totals, which we'll
*** print at the end of the report...

          LOCATE LAST.SPERSON IN SLSP.SUMMARY<1> BY "AL" SETTING LPOS ELSE
             SLSP.SUMMARY = INSERT(SLSP.SUMMARY,1,LPOS;LAST.SPERSON)

             *** Warehouse Sales...
             IF SLSP.TOTALS<1> THEN
                STOTALS           = LOWER(SLSP.TOTALS<1>)
                SOURCE.SUMMARY<1> = ADDS(SOURCE.SUMMARY<1>,SLSP.TOTALS<1>)
             END ELSE
                STOTALS = ''
             END

             SLSP.SUMMARY = INSERT(SLSP.SUMMARY,2,LPOS;STOTALS)

             *** Directs...
             IF SLSP.TOTALS<2> THEN
                STOTALS           = LOWER(SLSP.TOTALS<2>)
                SOURCE.SUMMARY<2> = ADDS(SOURCE.SUMMARY<2>,SLSP.TOTALS<2>)
             END ELSE
                STOTALS = ''
             END

             SLSP.SUMMARY = INSERT(SLSP.SUMMARY,3,LPOS;STOTALS)
          END

*** Clear out our totals...
          SLSP.TOTALS  = ''
          SLSP.ITEM.CT = 0

*** If they want to Page Break on Salespeople/Writers...
          IF PG.BREAK THEN

             *** Print a Credit Reason Summary for the Salesperson...
             SUMMARY.TITLE = '** CREDIT REASONS SUMMARY **'
             SUMMARY.ITEMS = SLSP.RSUMRY

             *** Go use our generic subroutine for looping through/printing
             *** all the Summary Lines...
             GOSUB PRINT.SUMMARY

             SLSP.RSUMRY   = ''

            * PRINT

             *** Print a Customer Summary for the Salesperson...
             SUMMARY.TITLE  = '** ':OCONV(LEVEL,"MCU")
             SUMMARY.TITLE := ' CUSTOMER SUMMARY **'

             SUMMARY.ITEMS  = SLSP.CSUMRY

             *** Go use our generic subroutine for looping through/printing
             *** all the Summary Lines...
             GOSUB PRINT.SUMMARY

             SLSP.CSUMRY    = ''

           *  PRINT CHAR(12)
          END

          RETURN
*-------------------------------------------------------------------------*
PRINT.TOTALS: * This is our generic code for printing Customer,
              * Salesperson/Writer, and Grand Totals...

          *** Print some dashed lines to separate our totals from the
          *** report detail...
          *PRINT SPACE(135):DASHED.LINES

          *** Sales Source & possibly who the Total line is for...
          *PRINT TOTAL.STRING               "R#133":'  ':
          *** Line Items...
          *PRINT TOTALS<1,1>                "R#10" :'  ':
          *** Item Qtys...
          *PRINT TOTALS<1,2>                "R#10" :'  ':
          *** Item Dollar Amount...
          *PRINT OCONV(TOTALS<1,3>,"MR9")   "R2#13"
          *PRINT

          RETURN
*-------------------------------------------------------------------------*
PRINT.SUMMARIES: * Print the Sales Source, Customer and Salesperson/Writer
                 * Summaries...

          *PRINT

         * IF NOT(PG.BREAK) THEN PRINT

          CONVERT '-' TO '=' IN DASHED.LINES

*** Sales Source Summary...
         * PRINT SPACE(86):'** SALES SOURCE SUMMARY **'
         * PRINT SPACE(135):DASHED.LINES

          IF SOURCE.SUMMARY<1> THEN
             SUMMARY.LINES = LOWER(SOURCE.SUMMARY<1>)
             TSTRING       = 'Warehouse Totals:'

             *** Go use our generic subroutine for printing a Summary line
             GOSUB PRINT.SUMMARY.LINE
          END

          IF SOURCE.SUMMARY<2> THEN
             SUMMARY.LINES = LOWER(SOURCE.SUMMARY<2>)
             TSTRING = 'Direct Totals:'

             *** Go use our generic subroutine for printing a Summary line
             GOSUB PRINT.SUMMARY.LINE
          END

        *  PRINT
       *   PRINT

*** Credit Reasons Summary...

          SUMMARY.TITLE = '** CREDIT REASONS SUMMARY **'
          SUMMARY.ITEMS = REASON.SUMMARY

          *** Go use our generic subroutine for looping through/printing
          *** all the Summary Lines...
          GOSUB PRINT.SUMMARY

          *PRINT
         * PRINT

*** Customer Summary...

          SUMMARY.TITLE = '** ':OCONV(LEVEL,"MCU"):' CUSTOMER SUMMARY **'
          SUMMARY.ITEMS = CUS.SUMMARY

          *** Go use our generic subroutine for looping through/printing
          *** all the Summary Lines...
          GOSUB PRINT.SUMMARY

        *  PRINT
        *  PRINT

*** Salesperson/Writer Summary...

          SUMMARY.TITLE = '** ':OCONV(SLCT,"MCU"):' SUMMARY **'
          SUMMARY.ITEMS = SLSP.SUMMARY

          *** Go use our generic subroutine for looping through/printing
          *** all the Summary Lines...
          GOSUB PRINT.SUMMARY

          RETURN
*-------------------------------------------------------------------------*
PRINT.SUMMARY: *** Print the Summary for whatever we come in here with,
               *** either Salespeople/Writers or Customers....

          *** Print the Entity that we're displaying the Summary for...
          *PRINT SPACE(86):SUMMARY.TITLE
          *PRINT SPACE(135):DASHED.LINES

          *** Count the Number of Summary Lines we need to print...
          SUMMARY.LINE.COUNT = DCOUNT(SUMMARY.ITEMS,VM)

          *** We'll list all the Warehouse Summary lines first and then
          *** all the Direct Summary lines...

          *** Our Sale Source is equal to 2 when we're dealing with a
          *** Warehouse sale, and 3 when we're dealing with a Direct...
          FOR SALE.SOURCE   = 2 TO 3
             IF SALE.SOURCE = 2 THEN
                TEMP.STRING = 'Warehouse Totals for '
             END ELSE
                TEMP.STRING = 'Direct Totals for '

                *** If we're about to print a Summary for Direct Sales,
                *** and we already printed a Summary for Warehouse Sales,
                *** then we'll print a blank line in btwn. the two...
                IF SUMMARY.ITEMS<2> AND SUMMARY.ITEMS<3> THEN
                   *PRINT
                END
             END

             FOR SCT = 1 TO SUMMARY.LINE.COUNT
                *** We'll need to trim off any spaces we might have added
                *** to make the entity get sorted first...
                SUM.ENTITY = TRIM(SUMMARY.ITEMS<1,SCT>)

                *** If we have Warehouse Summaries to print...
                IF SUMMARY.ITEMS<SALE.SOURCE,SCT> # '' THEN
                   SUMMARY.LINES = SUMMARY.ITEMS<SALE.SOURCE,SCT>
                   TSTRING       = TEMP.STRING:SUM.ENTITY

                   GOSUB PRINT.SUMMARY.LINE
                END
             NEXT SCT
          NEXT SALE.SOURCE

          RETURN
*-------------------------------------------------------------------------*
PRINT.SUMMARY.LINE: * This is our generic code for printing a single line
                    * of Summary data...

          *PRINT SPACE(89):
          *** Sales Source & possibly who the Summary line is for...
          *PRINT TSTRING                            "L#44":'  ':
          *** Line Items...
          *PRINT SUMMARY.LINES<1,1,1>               "R#10":'  ':
          *** Item Qtys...
          *PRINT SUMMARY.LINES<1,1,2>               "R#10":'  ':
          *** Item Dollar Amount...
          *PRINT OCONV(SUMMARY.LINES<1,1,3>,"MR9")  "R2#13"

          RETURN
*-------------------------------------------------------------------------*
!TSMITH~06/10/14~09:21
